package main

import (
	"net"
	"os"
	"os/signal"
	"syscall"
	"time"

	"gitee.com/sillyman/gocommon/utilities/randx"
	"gitee.com/sillyman/mixlog"

	"gitee.com/sillyman/pcaphelper"
	"gitee.com/sillyman/pcaphelper/applications/traffic/igmp"
	"gitee.com/sillyman/pcaphelper/applications/traffic/multicast"
)

var (
	quitCh = make(chan bool)
)

func main() {
	// 监听退出信号
	goHandleQuitSignal()

	txNetworkCardName := "enp2s0f0"
	tx, err := pcaphelper.New(txNetworkCardName)
	if err != nil {
		mixlog.Fatal(err.Error())
	}
	mixlog.Infof("已经绑定网卡：%s", txNetworkCardName)

	// 发射组播流
	go func() {
		mixlog.Info("即将开始发射组播流")
		defer func() {
			mixlog.Info("已经停止发射组播流")
		}()

		for range time.Tick(time.Millisecond * 2) {
			select {
			case <-quitCh:
				return
			default:
				dstIP := net.IPv4(239, 8, 8, byte(randx.IntMultiRange(randx.IntRange{Start: 1, End: 254})))
				vid := randx.IntMultiRange(randx.IntRange{Start: 1048, End: 1366})

				_ = tx.WritePacketData(multicast.BuildMulticastWithVLAN(
					net.HardwareAddr{0x00, 0x1e, 0x6e, 0x00, 0x00, 0x01}, uint16(vid),
					net.IPv4(10, 10, 228, 58),
					dstIP,
					5001, 5001,
				))
			}
		}
	}()

	// 发射组播流
	go func() {
		mixlog.Info("即将开始发射 IGMPv2 报告消息流")
		defer func() {
			mixlog.Info("已经停止发射 IGMPv2 报告消息流")
		}()

		for range time.Tick(time.Millisecond * 2) {
			select {
			case <-quitCh:
				return
			default:
				dstIP := net.IPv4(239, 8, 8, byte(randx.IntMultiRange(randx.IntRange{Start: 1, End: 254})))
				vid := randx.IntMultiRange(randx.IntRange{Start: 1048, End: 1366})

				_ = tx.WritePacketData(igmp.BuildIGMPv2ReportWithVLAN(
					net.HardwareAddr{0x00, 0x1e, 0x6e, 0x00, 0x00, 0x01}, uint16(vid),
					net.IPv4(10, 10, 228, 58),
					dstIP,
				))
			}
		}
	}()

	<-quitCh
	time.Sleep(time.Second)
}

func goHandleQuitSignal() {
	sigCh := make(chan os.Signal)
	signal.Notify(sigCh, syscall.SIGHUP, syscall.SIGINT, syscall.SIGQUIT, syscall.SIGTERM)

	go func() {
		mixlog.Infof("Got quit signal: %s", <-sigCh)
		close(quitCh)
		return
	}()
}
